package com.oa.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.oa.common.config.exception.OAException;
import com.oa.model.system.SysMenu;
import com.oa.model.system.SysRoleMenu;
import com.oa.system.service.SysRoleMenuService;
import com.oa.system.utils.MenuHelper;
import com.oa.system.mapper.SysMenuMapper;
import com.oa.system.mapper.SysRoleMenuMapper;
import com.oa.system.service.SysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oa.vo.system.AssginMenuVo;
import com.oa.vo.system.MetaVo;
import com.oa.vo.system.RouterVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author cloud_oa
 * @since 2024-10-06
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    //private SysRoleMenuMapper sysRoleMenuMapper;
    private SysRoleMenuService sysRoleMenuService;
    @Override
    public List<SysMenu> findNodes() {
        //查询所有菜单数据
        List<SysMenu> sysMenuList = baseMapper.selectList(null);
        //构建树形结构
        List<SysMenu> resultList = MenuHelper.buildTree(sysMenuList);
        return resultList;
    }

    @Override
    public List<SysMenu> findSysMenuByRoleId(Long roleId) {
        //全部权限列表
        //获取菜单表 查询所有菜单 条件状态为1
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus,1);
        //List<SysMenu> allSysMenuList = this.list(wrapper);
        List<SysMenu> allSysMenuList = baseMapper.selectList(wrapper);
        //根据角色id查询对应的菜单列表  根据角色id获取角色权限
        //List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(
        //        new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId,roleId));
        //获取角色菜单关系表 进行查询roleId
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuService.list(
                new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId,roleId)
        );

        //转换给角色id与角色权限对应的Map对象
        //根据获取的菜单id获取对应的菜单对象
        List<Long> menuIdList = sysRoleMenuList.stream()
                .map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        //拿菜单id和 所有菜单集合里id比较 存在相同 即封装
        allSysMenuList.forEach(permission ->{
            if(menuIdList.contains(permission.getId())){
                //根据属性 isSelect
                permission.setSelect(true);
            }else{
                permission.setSelect(false);
            }
        });
        //构建菜单树 返回规定格式的菜单列表
        List<SysMenu> sysMenuList = MenuHelper.buildTree(allSysMenuList);
        return sysMenuList;
    }
    @Transactional
    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId,assginMenuVo.getRoleId());
        //1 根据角色id 删除菜单角色表 分配数据
        sysRoleMenuService.remove(wrapper);

        for(Long menuId : assginMenuVo.getMenuIdList()){
            //2 从参数里面获取角色新分配菜单列表 进行遍历 将每个id数据添加进角色菜单关系表里
            if(StringUtils.isEmpty(menuId)) continue;
            SysRoleMenu rolePermission = new SysRoleMenu();
            rolePermission.setRoleId(assginMenuVo.getRoleId());
            rolePermission.setMenuId(menuId);
            //sysRoleMenuMapper.insert(rolePermission);
            sysRoleMenuService.save(rolePermission);
        }
    }

    @Override
    public void removeMenuById(Long id) {
        // 判断是否有子菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId,id);
        //int count = this.count(wrapper);
        //if(count > 0){
        //    throw new RuntimeException("不能删除有子菜单的菜单");
        //}

        Integer count = baseMapper.selectCount(wrapper);
        if(count > 0){
            throw new OAException(201,"不能删除有子菜单的菜单");
        }
        //this.removeById(id);
        baseMapper.deleteById(id);
    }

    //多表联查
    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List<SysMenu> sysMenuList = null;
        //判断当前用户是否管理员  userId = 1
        if(userId.longValue() == 1){
            //管理员 所有菜单列表
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysMenu::getStatus,1);
            wrapper.orderByAsc(SysMenu::getSortValue); //升序
            sysMenuList = baseMapper.selectList(wrapper);
        }else{
            //不是管理员  根据用户id查询用户所具有的菜单列表
            //根据用户id查询角色id  建立用户角色关系表 和 菜单表关系
            //用户角色关系表   角色菜单关系表  菜单表
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }

        //把查询出来的数据列表 构造成要求的路由数据结构
        //构造成树形结构
        List<SysMenu> sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
        //构造成路由结构
        List<RouterVo> routerList = this.buildRouter(sysMenuTreeList);
        return routerList;
    }
    //把查询出来的数据列表 构造成要求的路由数据结构
    private List<RouterVo> buildRouter(List<SysMenu> sysMenuTreeList) {
        //创建List集合 存储最终数据
        List<RouterVo> routerList = new ArrayList<>();
        for (SysMenu sysMenu : sysMenuTreeList) {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(sysMenu));
            router.setComponent(sysMenu.getComponent());
            router.setMeta(new MetaVo(sysMenu.getName(),sysMenu.getIcon()));
            //封装下层数据
            List<SysMenu> children = sysMenu.getChildren();
            if(sysMenu.getType().intValue() == 1){
                //加载下面隐藏路由
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                                .collect(Collectors.toList());
                for(SysMenu hiddenMenu : hiddenMenuList){
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(),hiddenMenu.getIcon()));
                    routerList.add(hiddenRouter);
                }
                //router.setChildren(buildRouter(children));
            }else{
                if(!CollectionUtils.isEmpty(children)){
                    if(children.size() > 0){
                        router.setAlwaysShow(true);
                    }
                    //递归
                    router.setChildren(buildRouter(children));
                }
            }
            routerList.add(router);
        }
        return routerList;
    }

    private String getRouterPath(SysMenu sysMenu) {
        String routerPath = "/" + sysMenu.getPath();
        if(sysMenu.getParentId().intValue() != 0) {
            routerPath = sysMenu.getPath();
        }
        return routerPath;
    }

    @Override
    public List<String> findUserPermsListByUserId(Long userId) {
        //判断是否管理员  管理员 返回查询所有按钮列表
        List<SysMenu> sysMenuList = null;
        if(userId.longValue() == 1){
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysMenu::getStatus,1);
            sysMenuList = baseMapper.selectList(wrapper);
        }else{
            //不是管理员  根据用户id查询用户所具有的按钮列表
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }

        //从查询出来的数据 获取可以操作的按钮值list集合  进行返回
        List<String> permsList = sysMenuList.stream()
                .filter(item -> item.getType() == 2)
                .map(item -> item.getPerms())
                .collect(Collectors.toList());
        return permsList;
    }


}
